package org.hxzon.demo.jt.logfilter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

public class LoggerFilterUtil {
    private static final int timeEndIndex = 15;
    private static final String encoding = "UTF-8";

    //01:37:06.406 error
    //00:19:59.115 REPEAT ABOVE
    //01:31:52.314 REPEAT ABOVE more line
    //01:19:44.926
    public static int filter(File src, File dst, Pattern filterPattern) throws IOException {
        int result = 0;
        // RandomAccessFile raf = new RandomAccessFile(src, "r");
        LineIterator it = FileUtils.lineIterator(src, "gbk");
        FileOutputStream fos = FileUtils.openOutputStream(dst);
        String linePre = null;
        String lineNext = null;
        boolean first = true;
        while (it.hasNext()) {

            //first,lineNext is null
            StringBuilder sbCur = new StringBuilder(lineNext == null ? "" : lineNext);
            while (it.hasNext()) {
                String line = it.next();
                if (isNewLog(line)) {
                    lineNext = line;
                    break;
                } else {
                    sbCur.append("\n" + line);
                }

            }
            if (!first) {

                //first,linePre is null
                //sub(linePre,timeEndIndex);
                String lineContentPre = linePre == null ? null : linePre.substring(timeEndIndex);
                String lineContentCur = sub(sbCur.toString(), timeEndIndex);
                if (lineContentCur.equals(lineContentPre)) {
                    fos.write((sbCur.substring(0, timeEndIndex) + "{REPEAT ABOVE}\n").getBytes(encoding));
                    result++;
                    //} else {
                } else if (filterPattern.matcher(lineContentCur).matches()) {
                    fos.write((sbCur.toString() + "\n").getBytes(encoding));
                    result++;
                    linePre = sbCur.toString();
                }
            }
            first = false;
        }
        // last line
        if (lineNext != null) {
            String lineContentPre = sub(linePre, timeEndIndex);
            String lineContentCur = sub(lineNext, timeEndIndex);
            if (lineContentCur.equals(lineContentPre)) {
                fos.write((lineNext.substring(0, timeEndIndex) + "{REPEAT ABOVE}\n").getBytes(encoding));
                result++;
                //} else {
            } else if (filterPattern.matcher(lineContentCur).matches()) {

                fos.write((lineNext.toString() + "\n").getBytes(encoding));
                result++;
            }
        }
        fos.close();
        return result;
    }

    private static String sub(String orig, int index) {
        if (orig == null || orig.length() < 15) {
            log(orig);
            return null;
        }
        return orig.substring(index);
    }

    private static boolean isNewLog(String line) {
        if (line.length() < 15) {
            return false;
        }
        String time = line.substring(0, timeEndIndex);
        if (time.charAt(0) == '[' && time.charAt(13) == ']' && time.charAt(14) == ' '//
                && time.charAt(3) == ':' && time.charAt(6) == ':' && time.charAt(9) == '.'//
                && isDigit(time, 1, 2, 4, 5, 7, 8, 10, 11, 12)) {
            return true;
        }
        return false;
    }

    private static boolean isDigit(String time, int... indexes) {
        for (int index : indexes) {
            char c = time.charAt(index);
            if (c < '0' && c > '9') {
                return false;
            }
        }
        return true;
    }

    private static void log(String msg) {
        System.out.println(msg);
    }

    public static void main(String[] args) throws IOException {
        String srcFilePath = "D:/work-juntai/训练题/日志筛选程序-测试数据/game 2011-12-22.log";
        String destFilePath = "D:/work-juntai/训练题/日志筛选程序-测试数据/f.log";
        String filterPattern = ".*Exception.*";
        //
        int patternMode = Pattern.DOTALL | Pattern.UNICODE_CASE | Pattern.MULTILINE//
                | Pattern.UNIX_LINES | Pattern.UNICODE_CHARACTER_CLASS;
        log("log count:" + LoggerFilterUtil.filter(new File(srcFilePath), new File(destFilePath), //
                Pattern.compile(filterPattern, patternMode)));

    }

}
